/////////////////////////////////////////////////////////////
//                      C++ Serialization                  //
//                                                         //
//  copyright:   (c) 2011 CPPS                             //
//  authors:     Hikki-Kun                                 //
//  mail:        glrenderable@gmail.com                    //
//                                                         //
//  This program is made available under the terms of      //
//  the MIT License.                                       //
/////////////////////////////////////////////////////////////
#ifndef SERIALIZATION_DISPATCHER_HPP
#define SERIALIZATION_DISPATCHER_HPP

namespace Serialization
{
  template <typename T>
  class Dispatcher {
    T m_invoked;
  public:
    Dispatcher(const T &invoked) : 
        m_invoked(invoked) { }

    template <typename T>
    void operator()(T &value, const std::string &name) {
      m_invoked.Dispatch(value, name);
    }

    template <typename T1, typename T2>
    void operator()(T1 &value1, const std::string &name1, 
                    T2 &value2, const std::string &name2) {
      m_invoked.Dispatch(value1, name1);
      m_invoked.Dispatch(value2, name2);
    }
    
    template <typename T1, typename T2, typename T3 >
    void operator()(T1 &value1, const std::string &name1, 
                    T2 &value2, const std::string &name2,
                    T3 &value3, const std::string &name3) {
      m_invoked.Dispatch(value1, name1);
      m_invoked.Dispatch(value2, name2);
      m_invoked.Dispatch(value3, name3);
    }

    template <typename T1, typename T2, typename T3, typename T4>
    void operator()(T1 &value1, const std::string &name1, 
                    T2 &value2, const std::string &name2,
                    T3 &value3, const std::string &name3,
                    T4 &value4, const std::string &name4) {
      m_invoked.Dispatch(value1, name1);
      m_invoked.Dispatch(value2, name2);
      m_invoked.Dispatch(value3, name3);
      m_invoked.Dispatch(value4, name4);
    }

    template <typename T1, typename T2, typename T3, 
              typename T4, typename T5>
    void operator()(T1 &value1, const std::string &name1, 
                    T2 &value2, const std::string &name2,
                    T3 &value3, const std::string &name3,
                    T4 &value4, const std::string &name4,
                    T5 &value5, const std::string &name5) {
      m_invoked.Dispatch(value1, name1);
      m_invoked.Dispatch(value2, name2);
      m_invoked.Dispatch(value3, name3);
      m_invoked.Dispatch(value4, name4);
      m_invoked.Dispatch(value5, name5);
    }

    template <typename T1, typename T2, typename T3, 
              typename T4, typename T5, typename T6>
    void operator()(T1 &value1, const std::string &name1, 
                    T2 &value2, const std::string &name2,
                    T3 &value3, const std::string &name3,
                    T4 &value4, const std::string &name4,
                    T5 &value5, const std::string &name5,
                    T5 &value6, const std::string &name6) {
      m_invoked.Dispatch(value1, name1);
      m_invoked.Dispatch(value2, name2);
      m_invoked.Dispatch(value3, name3);
      m_invoked.Dispatch(value4, name4);
      m_invoked.Dispatch(value5, name5);
      m_invoked.Dispatch(value6, name6);
    }

    template <typename T1, typename T2, typename T3, 
              typename T4, typename T5, typename T6, 
              typename T7>
    void operator()(T1 &value1, const std::string &name1, 
                    T2 &value2, const std::string &name2,
                    T3 &value3, const std::string &name3,
                    T4 &value4, const std::string &name4,
                    T5 &value5, const std::string &name5,
                    T6 &value6, const std::string &name6,
                    T7 &value7, const std::string &name7) {
      m_invoked.Dispatch(value1, name1);
      m_invoked.Dispatch(value2, name2);
      m_invoked.Dispatch(value3, name3);
      m_invoked.Dispatch(value4, name4);
      m_invoked.Dispatch(value5, name5);
      m_invoked.Dispatch(value6, name6);
      m_invoked.Dispatch(value7, name7);
    } 

    template <typename T1, typename T2, typename T3, 
              typename T4, typename T5, typename T6, 
              typename T7, typename T8>
    void operator()(T1 &value1, const std::string &name1, 
                    T2 &value2, const std::string &name2,
                    T3 &value3, const std::string &name3,
                    T4 &value4, const std::string &name4,
                    T5 &value5, const std::string &name5,
                    T6 &value6, const std::string &name6,
                    T7 &value7, const std::string &name7,
                    T8 &value8, const std::string &name8) {
      m_invoked.Dispatch(value1, name1);
      m_invoked.Dispatch(value2, name2);
      m_invoked.Dispatch(value3, name3);
      m_invoked.Dispatch(value4, name4);
      m_invoked.Dispatch(value5, name5);
      m_invoked.Dispatch(value6, name6);
      m_invoked.Dispatch(value7, name7);
      m_invoked.Dispatch(value8, name8);
    }

    template <typename T1, typename T2, typename T3, 
              typename T4, typename T5, typename T6, 
              typename T7, typename T8, typename T9>
    void operator()(T1 &value1, const std::string &name1, 
                    T2 &value2, const std::string &name2,
                    T3 &value3, const std::string &name3,
                    T4 &value4, const std::string &name4,
                    T5 &value5, const std::string &name5,
                    T6 &value6, const std::string &name6,
                    T7 &value7, const std::string &name7,
                    T8 &value8, const std::string &name8,
                    T9 &value9, const std::string &name9) {
      m_invoked.Dispatch(value1, name1);
      m_invoked.Dispatch(value2, name2);
      m_invoked.Dispatch(value3, name3);
      m_invoked.Dispatch(value4, name4);
      m_invoked.Dispatch(value5, name5);
      m_invoked.Dispatch(value6, name6);
      m_invoked.Dispatch(value7, name7);
      m_invoked.Dispatch(value8, name8);
      m_invoked.Dispatch(value9, name9);
    }

    template <typename T1, typename T2, typename T3, 
              typename T4, typename T5, typename T6, 
              typename T7, typename T8, typename T9, typename T0>
    void operator()(T1 &value1, const std::string &name1, 
                    T2 &value2, const std::string &name2,
                    T3 &value3, const std::string &name3,
                    T4 &value4, const std::string &name4,
                    T5 &value5, const std::string &name5,
                    T6 &value6, const std::string &name6,
                    T7 &value7, const std::string &name7,
                    T8 &value8, const std::string &name8,
                    T9 &value9, const std::string &name9,
                    T0 &value0, const std::string &name0) {
      m_invoked.Dispatch(value1, name1);
      m_invoked.Dispatch(value2, name2);
      m_invoked.Dispatch(value3, name3);
      m_invoked.Dispatch(value4, name4);
      m_invoked.Dispatch(value5, name5);
      m_invoked.Dispatch(value6, name6);
      m_invoked.Dispatch(value7, name7);
      m_invoked.Dispatch(value8, name8);
      m_invoked.Dispatch(value9, name9);
      m_invoked.Dispatch(value0, name0);
    }
  };
}

#endif